﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Configuration;
using System.Web.Script.Serialization;
using Microsoft.ApplicationBlocks.Data;
using EnglishRemix.Services.Model;
using EnglishRemix.Services.Utility;
using Newtonsoft.Json;
using System.Text.RegularExpressions;

using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Threading.Tasks;
using AlpineSoft;
using System.Diagnostics;

namespace EnglishRemix.Services
{
    public class UserFacade
    {
        private static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private static string connStr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
        string sqlStr = "";

        JavaScriptSerializer ser = new JavaScriptSerializer();

        public UserFacade()
        {
            log4net.Config.XmlConfigurator.Configure();
        }

        /*************************************** setUser *******************************************/

        public Response setUser(String Name, String route, String Password)
        {
            log.Debug("Setting User...");
            Response response = new Response();

            // Check to see if the user name has already been taken.
            sqlStr = "SELECT * FROM USERINFO where Name = '" + Name + "';";
            DataSet ds = SqlHelper.ExecuteDataset(connStr, CommandType.Text, sqlStr);
            if (ds != null && ds.Tables[0].Rows.Count > 0)
            {
                // Set response data
                response.result = "400";
                response.message = "Register Failed. Reason: User " + Name + " already exists.";
                return response;
            }

            // Create an usre object to save to the database.
            User user = new User();
            user.CreatedOn    = "'" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "'";
            user.LastLoginDate  = user.CreatedOn;
            user.Name   = "'" + Name + "'";
            user.Password    = "'" + Password + "'";
            
            // Assemble query string
            sqlStr = "INSERT INTO USERINFO (Name, Password, Email, ActivationStatus, Level, Coin, CreatedOn, LastLoginDate, LastModifiedBy) VALUES ("
                + user.Name + ","
                + user.Password + ","
                + user.Email + ","
                + user.ActivationStatus + ","
                + user.Level + ","
                + user.Coin + ","
                + user.CreatedOn + ","
                + user.LastLoginDate + ","
                + "'System'" + ");";

            try
            {                
                // Send a command to create a user.
                // If this step is done, a user will be created in the database regardless of method the user chose for the registration process.
                log.Debug("Sending command to create user. SQL:" + sqlStr);
                if (SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, sqlStr) != 1)
                {
                    response.result = "400";
                    response.message = "Registration failed. Reason: User creation failed.";
                    response.data = user;
                    return response;
                }

                // Takes care of the credentials
                switch (route)
                {
                    case "0":
                        {   // If user is created with a native credential, user registration is done.
                            response.result = "200";
                            response.message = "User successfully created with a native account.";
                            return response;
                        }
                    case "1":   // If user is created with a third party credential, contiune to update the credential in the table CREDENTIALS.
                    case "2":
                        break;
                    default:
                        {    // Unrecognized route error
                            response.result = "400";
                            response.message = "Registration failed. Reason: Unrecognized route. (b)";
                            return response;
                        }
                }

                // If user is created with a third party credential, update the credential in the table CREDENTIALS.
                string lastest_id = SqlHelper.ExecuteDataset(connStr, CommandType.Text, "SELECT TOP 1 Id FROM USERINFO ORDER BY Id DESC").Tables[0].Rows[0]["Id"].ToString();
                string updateCredStr = "INSERT INTO CREDENTIALS (UserInfo, SocialNetwork, Name) VALUES (" + lastest_id + ", " + route + ",'" + Name + "');";

                // Send a command to update user's third party credential.
                if (SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, updateCredStr) != 1)
                {
                    response.result = "400";
                    response.message = "Registration failed. Reason: Updating credential failed.";
                    return response;
                }

                response.result = "200";
                response.message = "User successfully created with third party account.";
                return response;
            }
            catch (Exception e)
            {
                response.result = "400";
                response.message = "An error happened when try to query database";
                return response;
                throw (e);
            }
        }

        /*************************************** getUser *******************************************/

        public Response getUser(String login_cred, String login_route, String usr_pwd)
        {
            Response response = new Response();
            string sqlStr = "";

            // Identify the route and corresponding credential. 
            // If there is a match, then the user is authenticated, return user info.
            switch (login_route)
            {
                case "0":
                    {
                        sqlStr = "SELECT * FROM USERINFO where Name = '" + login_cred + "' and Password = '" + usr_pwd + "';";
                        break;
                    }
                case "1":
                case "2":
                    {
                        sqlStr = "SELECT USERINFO.* FROM USERINFO, CREDENTIALS " +
                                    "where USERINFO.usr_id = CREDENTIALS.usr_id " +
                                    "and CREDENTIALS.credential_type = " + login_route +
                                    "and CREDENTIALS.credential_id = '" + login_cred +
                                    "';";
                        break;
                    }
                default:
                    {    // Route error
                        response.result = "400";
                        response.message = "Get user failed. Reason: Unrecognized route.";
                        return response;
                    }
            }

            try
            {
                DataSet ds = SqlHelper.ExecuteDataset(connStr, CommandType.Text, sqlStr);
                if (ds != null && ds.Tables.Count > 0)
                {
                    // Serialize the first user returned([0]) from database and send it back.
                    User user = new User(ds.Tables[0].Rows[0]);

                    // Get user's favorite 
                    List<String> obj = new List<string>();
                    user.favorites = obj;

                    // Set response data
                    response.result = "200";
                    response.message = "User data successfully returned.";
                    response.data = user;

                    // TODO: update lastlogtime

                    /*
                    foreach (DataRow eachRow in ds.Tables[0].Rows)
                    {
                        string name = eachRow["usr_id"].ToString();
                        result += eachRow["regtime"] + " ";
                        Console.WriteLine(name);
                    }
                    */
                }
                else
                {
                    // Set response data
                    response.result = "400";
                    response.message = "Can not find any data.";
                }

                return response;
            }
            catch (Exception e)
            {
                response.result = "400";
                response.message = "Invalid user name or password.";
                return response;
                throw (e);
            }
        }

        /*************************************** updateUser *******************************************/

        public string updateUser()
        {
            string sqlStr = "";
            //sqlCommand = sqlStr;
            try
            {
                if (SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, sqlStr) == 1)
                {
                    return "Database insert successful.";
                }
                else
                {
                    return "Database insert failed.";
                }
            }
            catch (Exception e)
            {
                return "An error happened when try to insert into database";
                throw (e);
            }
        }
    }
}